﻿using System;
using wbServo.cache;
using wbServo.dao;
using wbServo.domain;
using wbServo.entity;

namespace wbServo.service
{
    public class FuncService
    {
        private readonly object _lock = new object();
        public ResultData_FUNC ExecFunction(string funcName, string param)
        {
            //初始化过程相关的参数
            ResultData_FUNC result = new ResultData_FUNC
            {
                Code = "0",
                Msg = "success"
            };

            LogEntity logEntity = new LogEntity
            {
                WORK_NAME = "[流程-事件触发]-PLC",
                WORK_PROC = "FuncService.ExecFunction",
                WORK_CODE = "0",
                WORK_MSG = "success",
                CONT_NO = "",
                WORK_SEC = 1,
                CREATOR = 1001,
                CREATOR_NAME = "WCS",
                CREATE_DATE = DateTime.Now
            };

            if (!GlobalCachePool.single_plcItem_dict.TryGetValue(param, out PlcItemEntity item))
            {
                result.Code = "404";
                result.Msg = $"信号点[{param}]未在[PLC_ITEM]表中配置!]";
                return result;
            }

            if ("CREATE_POST".Equals(funcName))
            {
                logEntity.WORK_NAME = "[流程-MES任务]-PLC";
                //收到信息解析后创建POST
                lock (_lock)
                {
                    result = CreatePOST(item.ITEM_CODE, item.ITEM_VALUE);
                }
                //将确认信号的itemNo匹配出来        
                if (item.ITEM_NO.Substring(0,6) == "PLC_D1")
                {
                    string itemConfirm = item.ITEM_NO.Replace("PLC_D1", "AGV_D40001");
                    result.Writes = result.Writes + itemConfirm + "=1";
                }
                else if (item.ITEM_NO.Substring(0, 6) == "PLC_D3")
                {
                    string itemConfirm = item.ITEM_NO.Replace("PLC_D3", "AGV_D40002");
                    result.Writes = result.Writes + itemConfirm + "=1";
                }
                else if (item.ITEM_NO.Substring(0, 6) == "PLC_D5")
                {
                    string itemConfirm = item.ITEM_NO.Replace("PLC_D5", "AGV_D40003");
                    result.Writes = result.Writes + itemConfirm + "=1";
                }
                else if (item.ITEM_NO.Substring(0, 6) == "PLC_D7")
                {
                    string itemConfirm = item.ITEM_NO.Replace("PLC_D7", "AGV_D40004");
                    result.Writes = result.Writes + itemConfirm + "=1";
                }

            }
            else if ("CREATE_TASK_SL".Equals(funcName))
            {
                logEntity.WORK_NAME = "[流程-任务创建]-PLC";
                //收到信息解析后创建任务
                lock (_lock)
                {
                    result = CreateTaskSL(item.ITEM_CODE, item.ITEM_VALUE);
                }
                //将确认信号的itemNo匹配出来
                string itemConfirm = item.ITEM_NO.Replace("PLC_TO_AGV", "AGV_TO_PLC");
                result.Writes = result.Writes + itemConfirm + "=1";
            }
            else if ("CANCEL_TASK_XL".Equals(funcName))
            {
                logEntity.WORK_NAME = "[流程-任务创建]-PLC";
                //收到信息解析后创建任务
                lock (_lock)
                {
                    result = CreateTaskXL(item.ITEM_CODE, item.ITEM_VALUE);
                }
                //将确认信号的itemNo匹配出来
                string itemConfirm = item.ITEM_NO.Replace("PLC_TO_AGV", "AGV_TO_PLC");
                result.Writes = result.Writes + itemConfirm + "=1";
            }
            else if ("CANCEL_TASK".Equals(funcName))
            {
                logEntity.WORK_NAME = "[流程-任务取消]-PLC";
                //修改为精准匹配任务链
                lock (_lock)
                {
                    result = CancelTask(item.UNIT_NO, item.ITEM_VALUE);
                }
                //将确认信号的itemNo匹配出来
                string itemCancel = item.ITEM_NO.Replace("PLC_D6910", "AGV_D6915");
                result.Writes = result.Writes + itemCancel + "=" + item.ITEM_VALUE;
            }
            else
            {
                result.Code = "404";
                result.Msg = $"未匹配到相关方法{funcName}";
            }
            //记录日志
            logEntity.CONT_NO = param;
            logEntity.WORK_CODE = result.Code;
            logEntity.WORK_MSG = result.Msg;
            DBFactory.Insert2WorkLog(logEntity);

            //根据传入的参数获取对应的站台编号
            return result;
        }

        private ResultData_FUNC CreatePOST(string stnNo, string value)
        {
            ResultData_FUNC resultData = new ResultData_FUNC
            {
                Code = "0",
                Msg = "success",
                Writes = ""
            };
            try
            {
                string status = "0";
                //value值1为下料，2为上料，取料时status需为0，送料时status需为1
                if (value == "2")
                {
                    status = "1";
                }
                //检查一下postWms表当前站点是否有待上报指令
                string slSql = $"select * from wcs_post_wms where post_st=0 and cur_pos='{stnNo.Replace("'", "''")}' limit 1";
                PostWmsEntity slStn = DBFactory.QueryFirst<PostWmsEntity>(slSql);
                if (slStn != null)
                {
                    resultData.Msg = $"设备[{stnNo}]已有postWms待下发指令存在!";
                    return resultData;
                }
                PostWmsEntity postWms = new PostWmsEntity
                
                {
                    request_pk = DateTime.Now.ToString("yyyyMMddHHmmss"),
                    cont_no = "",
                    notice_type = "1",
                    cur_pos = stnNo,
                    status = status,
                    creator = 1001,
                    create_date = DateTime.Now
                };
                DBFactory.Insert2WcsPostWms(postWms);
           
                resultData.Msg = $"设备[{stnNo}]创建postWms指令成功!";
                return resultData;
            }
            catch (Exception ex)
            {
                resultData.Code = "create_task_error_500";
                /*resultData.Msg = $"设备[{unitNo}]创建任务{taskCode}链搬送任务失败!causeBy:{ex.Message}";*/
                resultData.Msg = $"设备[{stnNo}]创建postWms指令失败!causeBy:{ex.Message}";
                return resultData;
            }
        }

        private ResultData_FUNC CreateTaskSL(string stnNo, string value)
        {
            ResultData_FUNC resultData = new ResultData_FUNC
            {
                Code = "0",
                Msg = "success",
                Writes = ""
            };

            try
            {
                    //场景1：上料位请求满框
                    if (value == "1")
                    {
                        PostWmsEntity postWms = new PostWmsEntity
                        {
                            request_pk = DateTime.Now.ToString("yyyyMMddHHmmss"),
                            cont_no = "",
                            notice_type = "2",
                            cur_pos = stnNo,

                            creator = 1001,
                            create_date = DateTime.Now
                        };
                        DBFactory.Insert2WcsPostWms(postWms);

                        resultData.Msg = $"设备[{stnNo}]创建postWms指令成功!";
                        return resultData;
                    }
                //场景1：上料位请求空框
                if (value == "2")
                {
                    //检查一下缓存架是否有货
                    string slSql = $"select * from wcs_stn_mapping where status=2 and station_type='HW' limit 1";
                    StnMapEntity slStn = DBFactory.QueryFirst<StnMapEntity>(slSql);
                    if (slStn == null)
                    {
                        resultData.Code = "SL_err003";
                        resultData.Msg = $"上料位[{stnNo}]请求空框,缓存架无货!请等待!";
                        return resultData;
                    }
                    string fromPos = slStn.WCS_STATION;
                    //根据空框上料位与缓存架获取对应的任务链
                    string routeSql = $"select * from wcs_route_set where frm_pos='{fromPos}' and to_pos='{stnNo}' limit 1";

                    RouteSetEntity routePath = DBFactory.QueryFirst<RouteSetEntity>(routeSql);
                    if (routePath == null)
                    {
                        resultData.Code = "create_kx_error_01";
                        resultData.Msg = $"缓存架[{fromPos}]至空框上料工位[{stnNo}]未在wcs_route_set中配置搬送模板!请核查!";
                        return resultData;
                    }

                    //生成wcs_trk即可
                    TrkEntity wcsTrk = new TrkEntity
                    {
                        REQUEST_PK = DateTime.Now.ToString("yyyyMMddHHmmss"),
                        CONT_NO = stnNo + DateTime.Now.ToString("yyyyMMddHHmmss"),
                        DVC_NO = routePath.DVC_NO,
                        TRK_TYPE = "03",
                        TRK_PRTY = "1",
                        FRM_POS = fromPos,
                        TO_POS = stnNo,
                        CUR_POS = fromPos,

                        IS_FULL = "0",
                        GROUP_NO = "",
                        CREATOR = 1001,
                        CREATE_DATE = DateTime.Now
                    };

                    DBFactory.Insert2WcsTrk(wcsTrk);
                    //预分配站点状态
                    slStn.STATUS = 1;
                    slStn.COMMENTS = $"缓存架工位[{fromPos}]下料,预分配";
                    slStn.UPDATE_DATE = DateTime.Now;
                    DBFactory.UpdateStnMappingById(slStn);
                    //任务创建成功需要给PLC确认信号
                    resultData.Msg = $"空框上料工位[{stnNo}]请求成功!取货位置[{fromPos}]";
                }

                return resultData;
            }
            catch (Exception ex)
            {
                resultData.Code = "create_task_error_500";
                resultData.Msg = $"上料工位{stnNo}请求上料异常!causeBy:{ex.Message}"; ;
                return resultData;
            }
        }

        private ResultData_FUNC CreateTaskXL(string stnNo, string value)
        {
            ResultData_FUNC resultData = new ResultData_FUNC
            {
                Code = "0",
                Msg = "success",
                Writes = ""
            };

            try
            {
                    //场景1：下料位请求下满框
                    if (value == "1")
                    {
                        //检查一下缓存架是否有货
                        string slSql = $"select * from wcs_stn_mapping where status=0 and station_type='HW' limit 1";
                        StnMapEntity slStn = DBFactory.QueryFirst<StnMapEntity>(slSql);
                        if (slStn == null)
                        {
                            resultData.Code = "SL_err003";
                            resultData.Msg = $"工位[{stnNo}]满框下料,无可用缓存架!请等待!";
                            return resultData;
                        }
                        string toPos = slStn.WCS_STATION;
                        //根据下料位与缓存架获取对应的任务链
                        string routeSql = $"select * from wcs_route_set where frm_pos='{stnNo}' and to_pos='{toPos}' limit 1";

                        RouteSetEntity routePath = DBFactory.QueryFirst<RouteSetEntity>(routeSql);
                        if (routePath == null)
                        {
                            resultData.Code = "create_kx_error_01";
                            resultData.Msg = $"下料工位[{stnNo}]至缓存架[{toPos}]未在wcs_route_set中配置搬送模板!请核查!";
                            return resultData;
                        }

                        //生成wcs_trk即可
                        TrkEntity wcsTrk = new TrkEntity
                        {
                            REQUEST_PK = DateTime.Now.ToString("yyyyMMddHHmmss"),
                            CONT_NO = stnNo + DateTime.Now.ToString("yyyyMMddHHmmss"),
                            DVC_NO = routePath.DVC_NO,
                            TRK_TYPE = "03",
                            TRK_PRTY = "1",
                            FRM_POS = stnNo,
                            TO_POS = toPos,
                            CUR_POS = stnNo,

                            IS_FULL = "1",
                            GROUP_NO = "",
                            CREATOR = 1001,
                            CREATE_DATE = DateTime.Now
                        };

                        DBFactory.Insert2WcsTrk(wcsTrk);
                        //预分配站点状态
                        slStn.STATUS = 1;
                        slStn.COMMENTS = $"下料工位[{stnNo}]满框下料,预分配";
                        slStn.UPDATE_DATE = DateTime.Now;
                        DBFactory.UpdateStnMappingById(slStn);
                        //任务创建成功需要给PLC确认信号
                        resultData.Msg = $"下料工位[{stnNo}]请求成功!目标位置[{toPos}]";
                    }
                //场景2：下料位请求下空框
                if (value == "2")
                {
                    //检查一下缓存架是否有货
                    string slSql = $"select * from wcs_stn_mapping where status=0 and station_type='HW' limit 1";
                    StnMapEntity slStn = DBFactory.QueryFirst<StnMapEntity>(slSql);
                    if (slStn == null)
                    {
                        resultData.Code = "SL_err003";
                        resultData.Msg = $"工位[{stnNo}]空框下料,无可用缓存架!请等待!";
                        return resultData;
                    }
                    string toPos = slStn.WCS_STATION;
                    //根据下料位与缓存架获取对应的任务链
                    string routeSql = $"select * from wcs_route_set where frm_pos='{stnNo}' and to_pos='{toPos}' limit 1";

                    RouteSetEntity routePath = DBFactory.QueryFirst<RouteSetEntity>(routeSql);
                    if (routePath == null)
                    {
                        resultData.Code = "create_kx_error_01";
                        resultData.Msg = $"下料工位[{stnNo}]至缓存架[{toPos}]未在wcs_route_set中配置搬送模板!请核查!";
                        return resultData;
                    }

                    //生成wcs_trk即可
                    TrkEntity wcsTrk = new TrkEntity
                    {
                        REQUEST_PK = DateTime.Now.ToString("yyyyMMddHHmmss"),
                        CONT_NO = stnNo + DateTime.Now.ToString("yyyyMMddHHmmss"),
                        DVC_NO = routePath.DVC_NO,
                        TRK_TYPE = "03",
                        TRK_PRTY = "1",
                        FRM_POS = stnNo,
                        TO_POS = toPos,
                        CUR_POS = stnNo,

                        IS_FULL = "0",
                        GROUP_NO = "",
                        CREATOR = 1001,
                        CREATE_DATE = DateTime.Now
                    };

                    DBFactory.Insert2WcsTrk(wcsTrk);
                    //预分配站点状态
                    slStn.STATUS = 1;
                    slStn.COMMENTS = $"下料工位[{stnNo}]空框下料,预分配";
                    slStn.UPDATE_DATE = DateTime.Now;
                    DBFactory.UpdateStnMappingById(slStn);
                    //任务创建成功需要给PLC确认信号
                    resultData.Msg = $"下料工位[{stnNo}]请求成功!目标位置[{toPos}]";
                }

                return resultData;
            }
            catch (Exception ex)
            {
                resultData.Code = "create_taskXL_error_500";
                resultData.Msg = $"下料工位{stnNo}请求上料异常!causeBy:{ex.Message}"; ;
                return resultData;
            }
        }

        /// <summary>
        /// 精准取消任务链
        /// </summary>
        /// <param name="liftNo"></param>
        /// <returns></returns>
        private ResultData_FUNC CancelTask(string unitNo, string taskCode)
        {
            ResultData_FUNC resultData = new ResultData_FUNC
            {
                Code = "0",
                Msg = "success",
                Writes = ""
            };

            try
            {
                //判断一下WCS中是否存在可取消的任务
                string trkSql = $"select * from wcs_trk where unit_no='{unitNo}' and cont_no = '{taskCode}' and trk_st <2 limit 1";
                TrkEntity trk = DBFactory.QueryFirst<TrkEntity>(trkSql);
                if (trk == null)
                {
                    resultData.Code = "cancel_task_error_01";
                    resultData.Msg = $"设备[{unitNo}]不存在任务链[{taskCode}]的搬送任务,无需取消!";
                    return resultData;
                }
                //存在任务直接取消即可（同时取消对应的AGV搬送任务）
                trk.TRK_ST = 4;
                trk.UPDATE_DATE = DateTime.Now;
                trk.COMMENTS = $"派单系统对任务链{taskCode}的搬送任务进行取消操作!";
                DBFactory.UpdateTrkById(trk);
                //取消AGV相关任务
                string agvSql = $"select * from agv_trk_hk where trk_id={trk.TRK_ID} limit 1";
                AgvTrkEntity agvTrk = DBFactory.QueryFirst<AgvTrkEntity>(agvSql);
                if (agvTrk != null)
                {
                    agvTrk.STATUS = 40;
                    agvTrk.DATA = $"派单系统对任务链{taskCode}的搬送任务进行取消操作!";
                    //更新AGV任务的状态40
                    DBFactory.UpdateAgvTrkById(agvTrk);
                    resultData.Msg = $"同时取消AGV搬送任务[{agvTrk.TASK_CODE}]!";
                }
                //找到匹配的任务链并清空
                string plcSql = $"select * from plc_item where unit_no='{unitNo}' and item_value='{trk.CONT_NO}' and item_grp like 'TASK%' limit 1";
                PlcItemEntity plcItem = DBFactory.QueryFirst<PlcItemEntity>(plcSql);
                if (plcItem != null)
                {
                    resultData.Writes = plcItem.ITEM_NO + "=0;";
                }
                resultData.Msg = $"派单系统取消设备[{unitNo}]的任务链[{taskCode}]成功!" + resultData.Msg;
            }
            catch (Exception ex)
            {
                resultData.Code = "cancel_task_error_500";
                resultData.Msg = $"派单系统取消设备[{unitNo}]的任务链{taskCode}失败!causeBy:{ex.StackTrace}";
                return resultData;
            }

            return resultData;
        }
    }
}
